﻿using System;
using System.Collections.Generic;
using System.Web;
using PayRoller.Code;
using System.Web.SessionState;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using HySoft.Cash.Business;
using HySoft.Cash.Structure;
using System.Configuration;
using System.Web.Profile;
using Huayou.UI.WebControls;
using Huayou.Common;
using System.Data;
using System.Data.SqlClient;
using HySoft.Cash.BaseClass;
using System.Globalization;
using HySoft.Cash;
using HiLand.Utility.Enums.OP;

//Mark:此版本算法为先还付款,再还利息,最后还本金(真实还款和信用采用相同的计算方式)

namespace PayRoller.Include
{
    public partial class UInvoiceReceiving : CommonBaseControl
    {
        protected Huayou.UI.WebControls.DataGridTable dgdList;
        protected Label lblTip;
        public string OrgSid = "";
        protected TextBox txtParamstr;

        private string hrefReturnUrl = string.Empty;
        public string HrefReturnUrl
        {
            get
            {
                return this.hrefReturnUrl;
            }
            set
            {
                this.hrefReturnUrl = value;
            }
        }

        private int pageSize = 12;
        public int PageSize
        {
            get { return this.pageSize; }
            set { this.pageSize = value; }
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            this.dgdList.PageSize = this.pageSize;
        }

        protected void btnReceive_Click(object sender, EventArgs e)
        {
            decimal received = 0M;
            decimal orgCurrentBalance = Convert.ToDecimal(this.labCurrentBalance.Text);
            decimal orgClosingBalance = Convert.ToDecimal(this.labClosingBalance.Text);

            bool successful = decimal.TryParse(this.txtReceived.Text, out received);
            if (successful == true)
            {
                decimal totalUsable = received + Convert.ToDecimal(this.labRemainBalance.Text);
                decimal totalUsableForReciveInvoice = totalUsable;
                decimal totalPrincipalUsed = 0M;
                //decimal totalUsed = 0M;

                DataTable invoiceTable = GetInvoices();
                if (invoiceTable != null)
                {
                    /*
                    //1.1.第一循环，准备冲抵各种罚款(信用)
                    for (int i = invoiceTable.Rows.Count - 1; i >= 0; i--)
                    {
                        Guid invoiceID = new Guid(Convert.ToString(invoiceTable.Rows[i]["GUID"]));
                        decimal penaltyPaid = Convert.ToDecimal(invoiceTable.Rows[i]["PenaltyPaid"]);
                        decimal lateInterestChargesPaid = Convert.ToDecimal(invoiceTable.Rows[i]["LateInterestChargesPaid"]);
                        decimal penalty = Convert.ToDecimal(invoiceTable.Rows[i]["Penalty"]);
                        decimal lateInterestCharges = Convert.ToDecimal(invoiceTable.Rows[i]["LateInterestCharges"]);

                        decimal penaltyNeed = penalty - penaltyPaid;
                        decimal lateInterestChargesNeed = lateInterestCharges - lateInterestChargesPaid;

                        bool canContinue = DealInvoiceItemForCredit(invoiceID, "PenaltyPaid", penaltyNeed, ref totalUsable);
                        if (canContinue == false)
                        {
                            break;
                        }

                        canContinue = DealInvoiceItemForCredit(invoiceID, "LateInterestChargesPaid", lateInterestChargesNeed, ref totalUsable);
                        if (canContinue == false)
                        {
                            break;
                        }
                    }

                    //1.2.第二次循环，准备冲抵利息(信用)
                    for (int i = invoiceTable.Rows.Count - 1; i >= 0; i--)
                    {
                        Guid invoiceID = new Guid(Convert.ToString(invoiceTable.Rows[i]["GUID"]));

                        decimal interestPaid = Convert.ToDecimal(invoiceTable.Rows[i]["InterestPaid"]);
                        decimal interest = Convert.ToDecimal(invoiceTable.Rows[i]["Interest"]);
                        decimal interestNeed = interest - interestPaid;

                        bool canContinue = DealInvoiceItemForCredit(invoiceID, "InterestPaid", interestNeed, ref totalUsable);
                        if (canContinue == false)
                        {
                            break;
                        }
                    }

                    //1.3.第三次循环，准备冲抵本金(信用)
                    for (int i = invoiceTable.Rows.Count - 1; i >= 0; i--)
                    {
                        Guid invoiceID = new Guid(Convert.ToString(invoiceTable.Rows[i]["GUID"]));
                        decimal principalPaid = Convert.ToDecimal(invoiceTable.Rows[i]["PrincipalPaid"]);
                        decimal principal = Convert.ToDecimal(invoiceTable.Rows[i]["Principal"]);

                        decimal principalNeed = principal - principalPaid;

                        decimal totalUsableBefore = totalUsable;
                        bool canContinue = DealInvoiceItemForCredit(invoiceID, "PrincipalPaid", principalNeed, ref totalUsable);
                        decimal totalUsableAfter = totalUsable;
                        totalPrincipalUsed += (totalUsableBefore - totalUsableAfter);
                        if (canContinue == false)
                        {
                            break;
                        }
                    }
                    */
 
                    //2.0第四次循环，(真实对Invoice进行还款)
                    for (int i = invoiceTable.Rows.Count - 1; i >= 0; i--)
                    {
                        Guid invoiceID = new Guid(Convert.ToString(invoiceTable.Rows[i]["GUID"]));

                        decimal penaltyPaid = Convert.ToDecimal(invoiceTable.Rows[i]["PenaltyPaid"]);
                        decimal penalty = Convert.ToDecimal(invoiceTable.Rows[i]["Penalty"]);
                        decimal penaltyNeed = penalty - penaltyPaid;
                        bool canContinue = DealInvoiceItemForInvoice(invoiceID, "PenaltyPaid", penaltyNeed, ref totalUsableForReciveInvoice);
                        if (canContinue == false)
                        {
                            break;
                        }

                        decimal lateInterestChargesPaid = Convert.ToDecimal(invoiceTable.Rows[i]["LateInterestChargesPaid"]);
                        decimal lateInterestCharges = Convert.ToDecimal(invoiceTable.Rows[i]["LateInterestCharges"]);
                        decimal lateInterestChargesNeed = lateInterestCharges - lateInterestChargesPaid;
                        canContinue = DealInvoiceItemForInvoice(invoiceID, "LateInterestChargesPaid", lateInterestChargesNeed, ref totalUsableForReciveInvoice);
                        if (canContinue == false)
                        {
                            break;
                        }


                        decimal remainBalancePaid = Convert.ToDecimal(invoiceTable.Rows[i]["RemainBalancePaid"]);
                        
                        decimal interestPaid = Convert.ToDecimal(invoiceTable.Rows[i]["InterestPaid"]);
                        decimal interest = Convert.ToDecimal(invoiceTable.Rows[i]["Interest"]);

                        if (remainBalancePaid <= interest)
                        {
                            decimal interestNeed = interest - interestPaid - remainBalancePaid;
                            if (interestNeed > 0)
                            {
                                canContinue = DealInvoiceItemForInvoice(invoiceID, "InterestPaid", interestNeed, ref totalUsableForReciveInvoice);
                                if (canContinue == false)
                                {
                                    break;
                                }
                            }
                        }

                        

                        decimal principalPaid = Convert.ToDecimal(invoiceTable.Rows[i]["PrincipalPaid"]);
                        decimal principal = Convert.ToDecimal(invoiceTable.Rows[i]["Principal"]);

                        if (remainBalancePaid <= principal)
                        {
                            decimal principalNeed = 0;
                            if (remainBalancePaid > interest)
                            {
                                principalNeed = principal - (remainBalancePaid - interest) - principalPaid;
                            }
                            else
                            {
                                principalNeed = principal - principalPaid;
                            }

                            if (principalNeed > 0)
                            {
                                decimal totalUsableBefore = totalUsableForReciveInvoice;
                                canContinue = DealInvoiceItemForInvoice(invoiceID, "PrincipalPaid", principalNeed, ref totalUsableForReciveInvoice);
                                decimal totalUsableAfter = totalUsableForReciveInvoice;
                                totalPrincipalUsed += (totalUsableBefore - totalUsableAfter);
                                if (canContinue == false)
                                {
                                    break;
                                }
                            }
                        }
                        
                    }
                }

                string sqlUpdateInvoice = string.Empty;
                string sqlCapitalFlowing = string.Empty;
                string sqlCapitalRelate = string.Empty;
                if (needDealInvoiceInfoForInvoice.Count > 0)
                {
                    //一次收款可能被分配到多个资金流水账目里面，因此需要记录某个资金流水属于哪次收款
                    Guid receiveID = Guid.NewGuid();
                    DateTime receiveDate = SafeDateTime.LocalNow;
                    foreach (KeyValuePair<Guid, Dictionary<string, decimal>> kvp in needDealInvoiceInfoForInvoice)
                    {
                        Guid capitalFlowingID = Guid.NewGuid();
                        //sqlUpdateInvoice += string.Format("UPDATE [tInvoiceList] SET Guid= '{0}'", kvp.Key);
                        string sqlCapitalFlowingItem = string.Empty;
                        string sqlCapitalFlowingValue = string.Empty;
                        decimal totalPaidForCurrentInvoice = 0M;
                        foreach (KeyValuePair<string, decimal> kvpItem in kvp.Value)
                        {
                            totalPaidForCurrentInvoice += kvpItem.Value;
                            //sqlUpdateInvoice += string.Format(",{0}={0}+{1} ", kvpItem.Key, kvpItem.Value);
                            string fieldName = kvpItem.Key.ToLower();
                            sqlCapitalFlowingItem += string.Format(",[{0}]", fieldName.Substring(0, fieldName.IndexOf("paid")));
                            sqlCapitalFlowingValue += string.Format(",{0}", kvpItem.Value);

                            if (kvpItem.Key == "PrincipalPaid")
                            {
                                orgClosingBalance -= kvpItem.Value;
                            }
                            orgCurrentBalance -= kvpItem.Value;
                        }

                        sqlCapitalFlowingItem += ",[Total]";
                        sqlCapitalFlowingValue += string.Format(",{0}", totalPaidForCurrentInvoice);

                        string memoString = string.Format("it is a part of a recept.[{0}]", received);
                        sqlCapitalFlowing += string.Format("INSERT INTO [tCapitalFlowing] ([ID],[OrgID],[Direction],[TransDate],[LastCreditBalance],[LastFeeBalance],[ReceiveID],[memo]{0} ) VALUES ('{1}',{2},{3},'{7}',{5},{6},'{9}','{8}'{4});", sqlCapitalFlowingItem, capitalFlowingID, this.OrgSid, (int)CapitalFlowingDirections.Receive, sqlCapitalFlowingValue, orgClosingBalance, orgCurrentBalance, receiveDate, memoString,receiveID);

                        //sqlUpdateInvoice += string.Format(" where Guid= '{0}';", kvp.Key);
                        sqlCapitalRelate += string.Format("INSERT INTO [tCapitalFlowingRelating] ([Direction] ,[CapitalFlowingID] ,[RalatingID] ,[Memo]) VALUES ({0} ,'{1}' ,'{2}' ,'{3}');",
                            (int)CapitalFlowingDirections.Pay, capitalFlowingID, kvp.Key, "Invoice receive");
                    }
                }

                if (needDealInvoiceInfoForInvoice.Count > 0)
                {
                    foreach (KeyValuePair<Guid, Dictionary<string, decimal>> kvp in needDealInvoiceInfoForInvoice)
                    {
                        sqlUpdateInvoice += string.Format("UPDATE [tInvoiceList] SET Guid= '{0}'", kvp.Key);
                        foreach (KeyValuePair<string, decimal> kvpItem in kvp.Value)
                        {
                            sqlUpdateInvoice += string.Format(",{0}={0}+{1} ", kvpItem.Key, kvpItem.Value);
                        }

                        sqlUpdateInvoice += string.Format(" where Guid= '{0}';", kvp.Key);
                    }
                }

                string sqlCredit = string.Empty;
                if (totalUsableForReciveInvoice > 0)
                {
                    sqlCredit = string.Format("UPDATE [tOrgInfo]   SET [FeeBalance] = 0,[CreditBalance] = 0,[RemainBalance]={1} WHERE Sid={0}", this.OrgSid, totalUsableForReciveInvoice);
                }
                else
                {
                    sqlCredit = string.Format("UPDATE [tOrgInfo]   SET [FeeBalance] = [FeeBalance]-{1},[CreditBalance] = [CreditBalance]-{2},[RemainBalance]=0 WHERE Sid={0}", this.OrgSid, received, totalPrincipalUsed);
                }

                using (SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["SQLConnString"]))
                {
                    conn.Open();
                    SqlTransaction tran = conn.BeginTransaction();

                    try
                    {
                        //1.记录资金流动
                        if (string.IsNullOrEmpty(sqlCapitalFlowing) == false)
                        {
                            SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sqlCapitalFlowing);
                        }

                        if (string.IsNullOrEmpty(sqlCapitalRelate) == false)
                        {
                            SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sqlCapitalRelate);
                        }
                        //2.具体冲抵invoice的各种费用
                        if (string.IsNullOrEmpty(sqlUpdateInvoice) == false)
                        {
                            SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sqlUpdateInvoice);
                        }
                        //3.需要判断一下，是否需要关闭此Invoice的状态
                        SqlParameter[] commandParameters = new SqlParameter[] { new SqlParameter("@orgID", this.OrgSid), new SqlParameter("@closeStatus", (int)InvoiceStatuses.Closed) };
                        SqlHelper.ExecuteNonQuery(tran, CommandType.StoredProcedure, "TryCloseInvoice", commandParameters);

                        //4.更新Credit同时如果 还款还有结余那么 要记录在RemainBalance字段内
                        if (string.IsNullOrEmpty(sqlCredit) == false)
                        {
                            SqlHelper.ExecuteNonQuery(tran, CommandType.Text, sqlCredit);
                        }
                        tran.Commit();
                    }
                    catch
                    {
                        tran.Rollback();
                    }
                }

                this.txtReceived.Text = "0";
                this.LoadOrgInfo();
                this.dgdList.DataBind();
            }
        }

        /// <summary>
        /// 真实还款的Invoice还款的细节。其中guid 为invoice的GUID,string 为 Invoice的某个具体的费用项目,decimal为此项目的具体费用
        /// </summary>
        private Dictionary<Guid, Dictionary<string, decimal>> needDealInvoiceInfoForInvoice = new Dictionary<Guid, Dictionary<string, decimal>>();
        private bool DealInvoiceItemForInvoice(Guid invoiceID, string itemName, decimal itemValue, ref decimal totalUsable)
        {
            bool canContinue = true;
            if (itemValue > 0)
            {
                if (totalUsable > 0)
                {
                    decimal itemValueRemoved = 0M;
                    if (totalUsable >= itemValue)
                    {
                        totalUsable = totalUsable - itemValue;
                        itemValueRemoved = itemValue;
                    }
                    else
                    {
                        itemValueRemoved = totalUsable;
                        totalUsable = 0;
                        canContinue = false;
                    }

                    Dictionary<string, decimal> itemDic = null;
                    if (needDealInvoiceInfoForInvoice.ContainsKey(invoiceID))
                    {
                        itemDic = needDealInvoiceInfoForInvoice[invoiceID];
                    }
                    else
                    {
                        itemDic = new Dictionary<string, decimal>();
                        needDealInvoiceInfoForInvoice.Add(invoiceID, itemDic);
                    }

                    if (itemDic.ContainsKey(itemName))
                    {
                        itemDic[itemName] = itemValueRemoved;
                    }
                    else
                    {
                        itemDic.Add(itemName, itemValueRemoved);
                    }
                }
                else
                {
                    canContinue = false;
                }
            }

            return canContinue;
        }


        ///// <summary>
        ///// 为Credit拆分的对Invoice还款的细节。其中guid 为invoice的GUID,string 为 Invoice的某个具体的费用项目,decimal为此项目的具体费用
        ///// </summary>
        //private Dictionary<Guid, Dictionary<string, decimal>> needDealInvoiceInfoForCredit = new Dictionary<Guid, Dictionary<string, decimal>>();
        //private bool DealInvoiceItemForCredit(Guid invoiceID, string itemName, decimal itemValue, ref decimal totalUsable)
        //{
        //    bool canContinue = true;
        //    if (itemValue > 0)
        //    {
        //        if (totalUsable > 0)
        //        {
        //            decimal itemValueRemoved = 0M;
        //            if (totalUsable >= itemValue)
        //            {
        //                totalUsable = totalUsable - itemValue;
        //                itemValueRemoved = itemValue;
        //            }
        //            else
        //            {
        //                itemValueRemoved = totalUsable;
        //                totalUsable = 0;
        //                canContinue = false;
        //            }

        //            Dictionary<string, decimal> itemDic = null;
        //            if (needDealInvoiceInfoForCredit.ContainsKey(invoiceID))
        //            {
        //                itemDic = needDealInvoiceInfoForCredit[invoiceID];
        //            }
        //            else
        //            {
        //                itemDic = new Dictionary<string, decimal>();
        //                needDealInvoiceInfoForCredit.Add(invoiceID, itemDic);
        //            }

        //            if (itemDic.ContainsKey(itemName))
        //            {
        //                itemDic[itemName] = itemValueRemoved;
        //            }
        //            else
        //            {
        //                itemDic.Add(itemName, itemValueRemoved);
        //            }
        //        }
        //        else
        //        {
        //            canContinue = false;
        //        }
        //    }

        //    return canContinue;
        //}

        protected void bnSearch_Click(object sender, EventArgs e)
        {
            this.dgdList.DataBind();
        }

        protected void dgdList_CancelCommand(object source, DataGridCommandEventArgs e)
        {
            this.dgdList.EditItemIndex = -1;
            this.dgdList.DataBind();
        }

        protected void dgdList_DataBinding(object sender, EventArgs e)
        {
            DataTable dt = GetInvoices();
            CommonBasePage.SetPage(this.dgdList, dt);
            base.AddValue("pageno", Convert.ToString((int)(this.dgdList.CurrentPageIndex + 1)));
            this.txtParamstr.Text = base.PackPart(base.ParamValue);
        }

        private DataTable GetInvoices()
        {
            DataTable dt = new DataTable();
            using (TinvoicelistBN tbn = new TinvoicelistBN(this.Page))
            {
                tbn.Filter = string.Format(" OrgSid={0} and IsValid!={1} and IsValid!={2} ", base.Request["OrgSid"], (int)InvoiceStatuses.Closed, (int)InvoiceStatuses.Deleted); // " OrgSid=" + base.Request["OrgSid"].ToString() + " and IsValid!=2 and IsValid!=3 ";
                tbn.Order = "Sid desc";
                dt = tbn.GetList();
            }

            return dt;
        }

        protected void dgdList_EditCommand(object source, DataGridCommandEventArgs e)
        {
            this.dgdList.EditItemIndex = e.Item.ItemIndex;
            this.dgdList.DataBind();
        }

        protected void dgdList_ItemDataBound(object sender, DataGridItemEventArgs e)
        {
            if (e.Item.ItemIndex > -1)
            {
                DataRowView drv = e.Item.DataItem as DataRowView;
                if (drv != null)
                {
                    Label labStatus = e.Item.FindControl("labStatus") as Label;
                    if (labStatus != null)
                    {
                        InvoiceStatuses status = (InvoiceStatuses)Convert.ToInt32(drv["IsValid"]);
                        labStatus.Text = TinvoicelistBN.GetInvoiceStatusText(status); ;
                    }

                    Label labInvoiceAmount = e.Item.FindControl("labInvoiceAmount") as Label;
                    if (labInvoiceAmount != null)
                    {
                        labInvoiceAmount.Text = (Convert.ToDecimal(drv["Principal"]) + Convert.ToDecimal(drv["Interest"]) + Convert.ToDecimal(drv["Penalty"]) + Convert.ToDecimal(drv["LateInterestCharges"]) - Convert.ToDecimal(drv["RemainBalancePaid"])).ToString("0.00");
                    }

                    Label labReceiveAmount = e.Item.FindControl("labReceiveAmount") as Label;
                    if (labReceiveAmount != null)
                    {
                        labReceiveAmount.Text = (Convert.ToDecimal(drv["PrincipalPaid"]) + Convert.ToDecimal(drv["InterestPaid"]) + Convert.ToDecimal(drv["PenaltyPaid"]) + Convert.ToDecimal(drv["LateInterestChargesPaid"])).ToString("0.00");
                    }

                    Label labPreOverRollPaid = e.Item.FindControl("labPreOverRollPaid") as Label;
                    if (labPreOverRollPaid != null)
                    {
                        labPreOverRollPaid.Text = (Convert.ToDecimal(drv["RemainBalancePaid"])).ToString("0.00");
                    }
                }
            }
        }

        protected void dgdList_PageIndexChanged(object source, DataGridPageChangedEventArgs e)
        {
            this.dgdList.CurrentPageIndex = e.NewPageIndex;
            this.dgdList.DataBind();
        }

        protected void dgdList_UpdateCommand(object source, DataGridCommandEventArgs e)
        {
            string text = e.Item.Cells[0].Text;
            string str2 = ((TextBox)e.Item.Cells[3].Controls[0]).Text;
            SqlParameter[] commandParameters = new SqlParameter[] { new SqlParameter("@Sid", text), new SqlParameter("@dReceiveAmount", str2) };
            SqlHelper.ExecuteNonQuery(ConfigurationManager.AppSettings["SQLConnString"], CommandType.StoredProcedure, "UptReceiveAmount", commandParameters);
            this.dgdList.EditItemIndex = -1;
            this.dgdList.DataBind();
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (base.Request["OrgSid"] != null)
            {
                this.OrgSid = base.Request["OrgSid"].ToString();
            }

            this.LoadOrgInfo();

            if (!this.Page.IsPostBack)
            {
                base.ParamValue = base.UnPack();
                this.txtParamstr.Text = base.PackPart(base.ParamValue);
                string str = base.GetValue("pageno");
                if (str != null)
                {
                    this.dgdList.CurrentPageIndex = Convert.ToInt32(str) - 1;
                }
                this.dgdList.DataBind();

                if (this.hrefReturnUrl != string.Empty)
                {
                    this.hrefReturn.HRef = this.hrefReturnUrl;
                }
            }
            else
            {
                base.ParamValue = base.UnPackPart(this.txtParamstr.Text);
            }
        }

        private void LoadOrgInfo()
        {
            TorginfoDT entity = GetOrgInfo(Convert.ToInt32(this.OrgSid));
            if (entity != null)
            {
                this.labClientName.Text = entity.OrgName;
                this.labClientID.Text = this.OrgSid;
                this.labRemainBalance.Text = entity.RemainBalance.ToString("0.00");
                this.labClosingBalance.Text = entity.CreditBalance.ToString("0.00");
                this.labCurrentBalance.Text = entity.FeeBalance.ToString("0.00");
            }
        }


        private TorginfoDT GetOrgInfo(int orgID)
        {
            using (TorginfoBN bn = new TorginfoBN(this.Page))
            {
                TorginfoDT entity = bn.Get(orgID);
                return entity;
            }
        }
    }
}